package com.lonely.order.support.synchronizer.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lonely.common.exception.BusinessException;
import com.lonely.goods.enums.GoodsEnum;
import com.lonely.order.domain.dto.api.ClothCostFeeDetail;
import com.lonely.order.domain.dto.api.ClothCostFeeItem;
import com.lonely.order.domain.dto.api.QueryProduceOrderInfoByIdResDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderPart;
import com.lonely.order.domain.entity.SysOrderSecondProcess;
import com.lonely.order.enums.OrderSecondProcessEnum;
import com.lonely.order.service.IOrderSecondProcessService;
import com.lonely.order.service.IOrderService;
import com.lonely.order.support.synchronizer.SynchronizerOrderContext;
import com.lonely.order.threadlocals.OrderSynchronizedThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/31 15:30
 * @description: 同步订单二次工艺服务
 */
@Service
@Slf4j
public class SynchronizerOrderSecondProcessService {

    @Autowired
    private IOrderSecondProcessService orderSecondProcessService;

    @Autowired
    private IOrderService orderService;

    /**
     * 同步订单二次工艺数据
     *
     * @param synchronizerOrderContext
     * @param sysOrderPart
     * @param sheinPartCode
     */
    public void synchronizerOrderSecondProcess(SynchronizerOrderContext synchronizerOrderContext, SysOrderPart sysOrderPart, String sheinPartCode) {
        try {
            // 判断是否已存在
            int count = this.orderSecondProcessService.count(new LambdaQueryWrapper<SysOrderSecondProcess>()
                    .eq(SysOrderSecondProcess::getProduceOrderId, synchronizerOrderContext.getProduceOrderId())
                    .eq(SysOrderSecondProcess::getPartCode, sheinPartCode)
            );
            if (count > 0) {
                log.debug("同步订单号：{}对应的部件:{} 的二次工艺数据已存在,退出此次同步", synchronizerOrderContext.getProduceOrderId(), sheinPartCode);
                return;
            }

            // 创建部件二次工艺信息
            createOrderSecondProcesses(synchronizerOrderContext, sysOrderPart, sheinPartCode);
        } catch (Exception e) {
            log.error("同步订单号：{} 对应的部件: {} 的二次工艺数据失败", synchronizerOrderContext.getProduceOrderId(), sheinPartCode, e);
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 创建部件二次工艺信息
     *
     * @param synchronizerOrderContext
     * @param sysOrderPart
     * @param sheinPartCode
     * @return
     */
    private void createOrderSecondProcesses(SynchronizerOrderContext synchronizerOrderContext, SysOrderPart sysOrderPart, String sheinPartCode) {
        QueryProduceOrderInfoByIdResDTO orderInfoByIdResDTO = synchronizerOrderContext.getOrderInfoById();

        // 判断是否是首单
        boolean isFirst = StrUtil.isNotBlank(orderInfoByIdResDTO.getIsFirst()) && Objects.equals(orderInfoByIdResDTO.getIsFirst(), "首");
        Map<String, String> cuttingSecondProcessMap = new HashMap<>();
        if (!isFirst) {
            // 非首单，获取首单中的裁片二次工艺信息映射
            cuttingSecondProcessMap.putAll(firstOrderCuttingSecondProcessMap(orderInfoByIdResDTO.getSku()));
        }


        List<SysOrderSecondProcess> orderSecondProcesses = new ArrayList<>();
        orderSecondProcesses.addAll(this.extractPartSecondProcesses(orderInfoByIdResDTO, sysOrderPart, sheinPartCode, isFirst, cuttingSecondProcessMap));
        orderSecondProcesses.addAll(this.extractPartSecondProcessesInstance(orderInfoByIdResDTO, sysOrderPart, sheinPartCode));
        if (CollUtil.isNotEmpty(orderSecondProcesses)) {
            this.orderSecondProcessService.saveBatch(orderSecondProcesses);
        }
    }

    /**
     * 提取成衣二次工艺信息
     *
     * @param orderInfoByIdResDTO
     * @return
     */
    private List<SysOrderSecondProcess> extractPartSecondProcessesInstance(QueryProduceOrderInfoByIdResDTO orderInfoByIdResDTO, SysOrderPart sysOrderPart, String sheinPartCode) {

        // 获取二次工艺信息
        ClothCostFeeDetail secondProcessInstanceCost = orderInfoByIdResDTO.getClothCostFeeDetail().stream().filter(x -> Objects.equals("成衣二次工艺", x.getCategory())).findFirst().orElse(null);
        if (secondProcessInstanceCost == null) {
            return new ArrayList<>();
        }
        return this.batchConvertSecondProcessItem2SysOrderSecondProcess(secondProcessInstanceCost.getClothCostFeeDetail(), sysOrderPart, GoodsEnum.GoodsSecondProcessTypeEnum.READY_TO_WEAR.getType(),
                sheinPartCode, false, null);
    }


    /**
     * 提取面辅料二次工艺信息
     *
     * @param orderInfoByIdResDTO
     * @return
     */
    private List<SysOrderSecondProcess> extractPartSecondProcesses(QueryProduceOrderInfoByIdResDTO orderInfoByIdResDTO, SysOrderPart sysOrderPart, String sheinPartCode, boolean isFirst,
                                                                   Map<String, String> cuttingSecondProcessMap) {

        // 获取二次工艺信息
        ClothCostFeeDetail secondProcessCost = orderInfoByIdResDTO.getClothCostFeeDetail().stream().filter(x -> Objects.equals("面辅料二次工艺", x.getCategory())).findFirst().orElse(null);
        if (secondProcessCost == null || CollUtil.isEmpty(secondProcessCost.getClothCostFeeDetail())) {
            return new ArrayList<>();
        }

        return this.batchConvertSecondProcessItem2SysOrderSecondProcess(secondProcessCost.getClothCostFeeDetail(), sysOrderPart,
                GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType(), sheinPartCode, isFirst, cuttingSecondProcessMap);
    }

    /**
     * 批量将二次工艺信息转换成 SysOrderSecondProcess 对象
     *
     * @param clothCostFeeItems
     * @param sysOrderPart
     * @param type
     * @param sheinPartCode
     * @return
     */
    private List<SysOrderSecondProcess> batchConvertSecondProcessItem2SysOrderSecondProcess(List<ClothCostFeeItem> clothCostFeeItems, SysOrderPart sysOrderPart, Integer type,
                                                                                            String sheinPartCode, boolean isFirst, Map<String, String> cuttingSecondProcessMap) {
        List<SysOrderSecondProcess> result = new ArrayList<>();
        for (ClothCostFeeItem currentSecondProcess : clothCostFeeItems) {
            // 判断部件id是否匹配
            if (!Objects.equals(StrUtil.nullToEmpty(sheinPartCode), StrUtil.nullToEmpty(currentSecondProcess.getPartCode()))) {
                continue;
            }

            SysOrderSecondProcess orderSecondProcess = new SysOrderSecondProcess();
            orderSecondProcess.setOrderId(sysOrderPart.getOrderId());
            orderSecondProcess.setOrderPartId(sysOrderPart.getId());
            orderSecondProcess.setProduceOrderId(sysOrderPart.getProduceOrderId());
            orderSecondProcess.setPartCode(sheinPartCode);
            orderSecondProcess.setType(type);
            orderSecondProcess.setUnitPrice(Convert.toStr(currentSecondProcess.getUnitPrice()));
            orderSecondProcess.setSimpleUse(currentSecondProcess.getSimpleUse());

            if (StrUtil.isNotBlank(currentSecondProcess.getTitle())) {
                int startIndex = currentSecondProcess.getTitle().indexOf("/");
                orderSecondProcess.setProcessName(currentSecondProcess.getTitle().substring(0, startIndex));
                orderSecondProcess.setSupplierName(currentSecondProcess.getTitle().substring(startIndex + 1));
            }

            orderSecondProcess.setCreateBy(OrderSynchronizedThreadLocal.getCreateBy());
            orderSecondProcess.setUpdateBy(OrderSynchronizedThreadLocal.getCreateBy());

            if (Objects.equals(type, GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType())) {
                // 面辅料二次工艺，需要根据情况设置状态
                // 判断是否是首单
                if (isFirst) {
                    orderSecondProcess.setCuttingSecondProcess(null);
                    orderSecondProcess.setStatus(OrderSecondProcessEnum.StatusEnum.TO_BE_CONFIRMED.getStatus());
                } else {
                    // 非首单，需要判断首单中该工艺的裁片二次工艺状态
                    if (cuttingSecondProcessMap.containsKey(orderSecondProcess.getProcessName())) {
                        String cuttingSecondProcess = cuttingSecondProcessMap.get(orderSecondProcess.getProcessName());
                        orderSecondProcess.setCuttingSecondProcess(cuttingSecondProcess);
                        if (StrUtil.isEmpty(cuttingSecondProcess)) {
                            orderSecondProcess.setStatus(OrderSecondProcessEnum.StatusEnum.TO_BE_CONFIRMED.getStatus());
                        } else {
                            orderSecondProcess.setStatus(OrderSecondProcessEnum.StatusEnum.TO_GO.getStatus());
                        }
                    } else {
                        // 虽然是非首单，但是存在从shein接口过来的直接就是返单数据，此时需要设置状态为待发起
                        orderSecondProcess.setCuttingSecondProcess(null);
                        orderSecondProcess.setStatus(OrderSecondProcessEnum.StatusEnum.TO_BE_CONFIRMED.getStatus());
                    }
                }
            }

            result.add(orderSecondProcess);
        }
        return result;
    }

    /**
     * 获取该sku对应的首单中裁片二次工艺数据映射
     *
     * @param sku
     * @return
     */
    private Map<String, String> firstOrderCuttingSecondProcessMap(String sku) {
        SysOrder sysOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>()
                .eq(SysOrder::getSku, sku)
                .eq(SysOrder::getIsFirst, 1)
        );
        if (sysOrder == null) {
            // 该sku没有首单订单
            return new HashMap<>();
        }

        return this.orderSecondProcessService.list(new LambdaQueryWrapper<SysOrderSecondProcess>()
                .eq(SysOrderSecondProcess::getOrderId, sysOrder.getId())
                .eq(SysOrderSecondProcess::getType, GoodsEnum.GoodsSecondProcessTypeEnum.DOUGH_AND_AUXILIARY_MATERIALS.getType())
        ).stream().collect(Collectors.toMap(SysOrderSecondProcess::getProcessName,
                x -> StrUtil.nullToEmpty(x.getCuttingSecondProcess()), (a, b) -> b));
    }

}
